package med.config;

import java.lang.reflect.Field;

public class Config {

	private static Config instance = new Config();

	private Boolean useStemmerParam;
	private Boolean parseDatesParam;
	private Integer vectorLengthParam;
	private Integer tagPositionParam;
	private Integer maxDepthParam;

	private class Defaults {
		private static final int MAX_DEPTH_DEFAULT = 1;
		private static final int VECTOR_LENGTH_DEFAULT = 7;
		private static final int TAG_POSITION_DEFAULT = -3;
		private static final boolean USE_STEMMER_DEFAULT = false;
		private static final boolean PARSE_DATES_DEFAULT = true;
	}

	public static Config getInstance() {
		return instance;
	}

	public boolean isUseStemmerParam() {
		return useStemmerParam;
	}

	public Integer getVectorLengthParam() {
		return vectorLengthParam;
	}

	public Integer getTagPositionParam() {
		return tagPositionParam;
	}

	public Integer getMaxDepthParam() {
		return maxDepthParam;
	}
	
	public boolean isParseDatesParam() {
		return parseDatesParam;
	}

	/**
	 * Do not use directly. Use {@link #getInstance()} instead.
	 */
	private Config() {
	}

	public void parseArgs(String[] args) {
		try {
			for (String arg : args) {
				if (arg.startsWith("-vlen:")) {
					vectorLengthParam = Integer.valueOf(getValueFromArg(arg));
					tagPositionParam = vectorLengthParam + Defaults.TAG_POSITION_DEFAULT;
				} else if (arg.startsWith("-s")) {
					useStemmerParam = true;
				} else if (arg.startsWith("-depth:")) {
					maxDepthParam = Integer.valueOf(getValueFromArg(arg));
				}
			}

			if (vectorLengthParam == null) {
				vectorLengthParam = Defaults.VECTOR_LENGTH_DEFAULT;
			}

			if (useStemmerParam == null) {
				useStemmerParam = Defaults.USE_STEMMER_DEFAULT;
			}

			if (tagPositionParam == null) {
				tagPositionParam = Defaults.VECTOR_LENGTH_DEFAULT + Defaults.TAG_POSITION_DEFAULT;
			}

			if (maxDepthParam == null) {
				maxDepthParam = Defaults.MAX_DEPTH_DEFAULT;
			}

			if (parseDatesParam == null) {
				parseDatesParam = Defaults.PARSE_DATES_DEFAULT;
			}

			validate();
		} catch (Exception ignore) {
			usage();
		}
	}

	private void validate() {
		for (Field field : this.getClass().getDeclaredFields()) {
			try {
				if (field.getName().endsWith("Param")
						&& field.get(this) == null) {
					throw new RuntimeException();
				}
			} catch (Exception ex) {
				throw new RuntimeException(ex);
			}
		}
	}

	private static String getValueFromArg(String arg) {
		return arg.substring(arg.indexOf(":") + 1);
	}

	private void usage() {
		System.out.println("optional parameters: -vlen:<vector_length> (def: 5) -depth:<max_depth> (def: 1) -s");
		throw new RuntimeException();
	}
}
